package com.fudan.es;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.http.HttpHost;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest.Level;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
import org.elasticsearch.action.fieldcaps.FieldCapabilities;
import org.elasticsearch.action.fieldcaps.FieldCapabilitiesRequest;
import org.elasticsearch.action.fieldcaps.FieldCapabilitiesResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.cluster.health.ClusterIndexHealth;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.fudan.biz.data.entity.DataWarehouse;
import com.fudan.biz.data.service.DataWarehouseService;
import com.fudan.es.entity.FieldMeta;
import com.fudan.framework.utils.StringUtils;

@Component
public class EsClient {

	private static Map<Integer,RestHighLevelClient> clientMap = new ConcurrentHashMap<>();

	@Autowired
	private DataWarehouseService dataWarehouseService;

	public RestHighLevelClient getClientByDataWareId(Integer dwId) {
		DataWarehouse dataWarehouse = dataWarehouseService.get(dwId);
		if(dataWarehouse != null) {
			if(clientMap.containsKey(dwId)) {
				return clientMap.get(dwId);
			}else {
				RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost(dataWarehouse.getHost(), dataWarehouse.getPort(), "http")));
				clientMap.put(dwId, client);
				return client;
			}
		}else {
			throw new RuntimeException("no ds found!");
		}
	}

	public RestHighLevelClient getClient(String dsId) {
		if(dsId.matches("[0-9]+")) {
			return getClientByDataWareId(Integer.parseInt(dsId));
		}
		throw new RuntimeException("ds id illegal");
	}

	public RestHighLevelClient getClient(Integer dwId) {
		return getClientByDataWareId(dwId);
	}

	public static void main(String[] args) throws IOException {

		RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("10.141.222.31", 9200, "http")));


		//GetMappingsResponse mappingResponse = client.indices().getMapping(new GetMappingsRequest().indices("dataset_mix3"), RequestOptions.DEFAULT);
//		ClusterHealthRequest request = new ClusterHealthRequest();
//		ClusterHealthResponse response = client.cluster().health(request, RequestOptions.DEFAULT);
//		Map<String, ClusterIndexHealth> indices = response.getIndices();
//		Set<String> set = indices.keySet();
//		for (String string : set) {
//			System.out.println(string+": "+indices.get(string));
//		}
//		GetIndexResponse indexResponse = client.indices().get(new GetIndexRequest("/"), RequestOptions.DEFAULT);
//		SearchRequest request = new SearchRequest("dataset_mix3")
//		.source(new SearchSourceBuilder().size(0).query(QueryBuilders.boolQuery().must(QueryBuilders.termQuery("obj_aoi.result.keyword", "fail"))).aggregation(Aggs.nested("nest", "nested_aoi")
//				.subAggregation(Aggs.
//						filter("f", Querys.terms("nested_aoi.result.keyword", "fail"))
//						.subAggregation(Aggs.nested("n2","nested_aoi.nested_errorCode").subAggregation(Aggs.
//								terms("t","nested_aoi.nested_errorCode.error.keyword"))))));
//		BoolQueryBuilder q = QueryBuilders.boolQuery().must(QueryBuilders.termQuery("tag_ft", 1)).must(QueryBuilders.termQuery("st_ft_fp", 1)).must(QueryBuilders.termQuery("obj_wo.PRODUCT_MODEL.keyword", "AC018"));
//		AggsBuilder aggs = AggsBuilder.build(Aggs.nested("tn","nested_ft")).subAggs(AggsBuilder.build(Aggs.terms("t", "nested_ft.stationCode.keyword").subAggregation(AggregationBuilders.reverseNested("r"))));

		ClusterHealthRequest request = new ClusterHealthRequest();
		request.level(Level.INDICES);
		ClusterHealthResponse response = client.cluster().health(request, RequestOptions.DEFAULT);
		Map<String, ClusterIndexHealth> indices = response.getIndices();
		Set<String> indicesSet = indices.keySet();
		for (String index : indicesSet) {
			System.out.println(index);
		}
		System.out.println("================================");
		client.close();
	}

	static void parseProperties(List<FieldMeta> fieldList,FieldMeta parent,Map<String,Object> map) {
		if(map == null) return;
		Map<String,Object> properties = (Map<String, Object>) map.get("properties");
		if(properties!=null) {
			Set<String> fieldNames = properties.keySet();
			for (String fieldName : fieldNames) {
				FieldMeta meta = new FieldMeta(false,false);
				FieldMeta keyMeta = null;
				Map<String,Object> fieldInfo = (Map<String, Object>) properties.get(fieldName);
				String type = (String) fieldInfo.get("type");
				if(type == null) {
					type = "object";
				}
				meta.setType(type);
				Map<String,Object> fields = (Map<String, Object>) fieldInfo.get("fields");
				if(fields!=null) {
					Map<String,Object> keyword = (Map<String, Object>) fields.get("keyword");
					if(keyword!=null) {
						String keyType = (String) keyword.get("type");
						if("keyword".equals(keyType)) {
							keyMeta = new FieldMeta(false,false);
							keyMeta.setType(keyType);
						}
					}
				}
				if(parent != null) {
					if("nested".equals(parent.getType())) {
						meta.nested(true).nestedPath(parent.getName());
						if(keyMeta != null) {
							keyMeta.nested(true).nestedPath(parent.getName());
						}
					}
					meta.setName(StringUtils.concat(parent.getName(),".",fieldName));
					if(keyMeta != null) {
						keyMeta.setName(StringUtils.concat(parent.getName(),".",fieldName,".keyword"));
					}
				}else {
					meta.setName(fieldName);
					if(keyMeta != null) {
						keyMeta.setName(StringUtils.concat(fieldName,".keyword"));
					}
				}
				fieldList.add(meta);
				if(keyMeta!=null) {
					fieldList.add(keyMeta);
				}
				parseProperties(fieldList,meta,fieldInfo);
			}
		}
	}

	static void fillAbility(List<FieldMeta> fieldList,String index) throws IOException {
		RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("10.141.222.31", 9200, "http")));
		FieldCapabilitiesResponse fieldCaps = client.fieldCaps(new FieldCapabilitiesRequest().indices(index).fields("*"), RequestOptions.DEFAULT);
		for (FieldMeta fieldMeta : fieldList) {
			Map<String, FieldCapabilities> fieldCap = fieldCaps.getField(fieldMeta.getName());
			if(fieldCap == null) {
				continue;
			}
			boolean searchable = fieldCap.get(fieldMeta.getType()).isSearchable();
			boolean aggregatable = fieldCap.get(fieldMeta.getType()).isAggregatable();
			fieldMeta.setSearchable(searchable);
			fieldMeta.setAggregatable(aggregatable);
		}
	}

//	static void doSearch() throws Exception {
//		TermQueryBuilder termQuery = QueryBuilders.termQuery("tableNam.keyword", "TEMP_PRODUCT_SHOP");
//		SearchSourceBuilder builder = new SearchSourceBuilder();
//		SearchSourceBuilder qb = builder.query(termQuery).size(5);
//		SearchRequest request = new SearchRequest("dataset_tmp");
//		request.source(qb);
//		SearchResponse response = getClient().search(request, RequestOptions.DEFAULT);
//		SearchHit[] hits = response.getHits().getHits();
//		for (SearchHit searchHit : hits) {
//			System.out.println(searchHit.getSourceAsMap());
//		}
//	}
}
